﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace GenericStateMachine.Test
{
    [TestClass]
    public class TestScenarios
    {
        [TestMethod]
        public void TestNormalShutdown()
        {
            Debug.WriteLine("<< new SampleService()");
            var service = new SampleService().AsDynamic();
            Assert.AreEqual(SampleService.ServiceState.Created, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> new SampleService()");

            Debug.WriteLine(string.Empty);

            Debug.WriteLine("<< SampleService.Start");
            service.Start();
            Assert.AreEqual(SampleService.ServiceState.RequestWaiting, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> SampleService.Start");

            Debug.WriteLine(string.Empty);

            Debug.WriteLine("<< SampleService.HandleRequest(test)");
            service.HandleRequest("test");
            Assert.AreEqual(SampleService.ServiceState.RequestWaiting, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> SampleService.HandleRequest(test)");

            Debug.WriteLine(string.Empty);

            Debug.WriteLine("<< SampleService.Stop");
            service.Stop();
            Assert.AreEqual(SampleService.ServiceState.Stopped, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> SampleService.Stop");

            Debug.WriteLine(string.Empty);

            Debug.WriteLine("<< SampleService.Abort");
            service.Abort();
            Assert.AreEqual(SampleService.ServiceState.Stopped, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> SampleService.Abort");
        }

        [TestMethod]
        public void TestAbort()
        {
            Debug.WriteLine("<< new SampleService()");
            var service = new SampleService().AsDynamic();
            Assert.AreEqual(SampleService.ServiceState.Created, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> new SampleService()");

            Debug.WriteLine(string.Empty);

            Debug.WriteLine("<< SampleService.Start");
            service.Start();
            Assert.AreEqual(SampleService.ServiceState.RequestWaiting, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> SampleService.Start");

            Debug.WriteLine(string.Empty);

            Debug.WriteLine("<< SampleService.Abort");
            service.Abort();
            Assert.AreEqual(SampleService.ServiceState.Aborted, service.stateMachine.CurrentState);
            Assert.AreEqual(false, service.stateMachine.IsBusy());
            Debug.WriteLine(">> SampleService.Abort");
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void TestInvalidStateException1()
        {
            try
            {
                Debug.WriteLine("<< new SampleService()");
                var service = new SampleService();
                Debug.WriteLine(">> new SampleService()");

                Debug.WriteLine(string.Empty);

                Debug.WriteLine("<< SampleService.Start");
                service.Start();
                Debug.WriteLine(">> SampleService.Start");

                Debug.WriteLine(string.Empty);
                Debug.WriteLine(string.Empty);

                Debug.WriteLine("<< SampleService.Start");
                service.Start();
                Debug.WriteLine(">> SampleService.Start");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("{0}: {1}", ex.GetType().Name, ex.Message));
                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void TestInvalidStateException2()
        {
            try
            {
                Debug.WriteLine("<< new SampleService()");
                var service = new SampleService();
                Debug.WriteLine(">> new SampleService()");

                Debug.WriteLine(string.Empty);

                Debug.WriteLine("<< SampleService.Start");
                service.Start();
                Debug.WriteLine(">> SampleService.Start");

                Debug.WriteLine(string.Empty);

                Debug.WriteLine("<< SampleService.Stop");
                service.Stop();
                Debug.WriteLine(">> SampleService.Stop");

                Debug.WriteLine(string.Empty);
                Debug.WriteLine(string.Empty);

                Debug.WriteLine("<< SampleService.Stop");
                service.Stop();
                Debug.WriteLine(">> SampleService.Stop");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("{0}: {1}", ex.GetType().Name, ex.Message));
                throw;
            }
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void TestInvalidSetting()
        {
            try
            {
                Debug.WriteLine("<< new SampleInvalidService()");
                var service = new SampleInvalidService();
                Debug.WriteLine(">> new SampleInvalidService()");
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("{0}: {1}", ex.GetType().Name, ex.Message));
                throw;
            }
        }
    }
}
